/*
 * BigButton -- Arduino sketch to be the big button for the "in-space" sign
 * ---------
 *
 * Meant to be used with bigButtonServer.pl
 *
 * Input:
 * -----
 * The sketch has one physical input, a button connected to pin 'swPin'.
 * It is an on-off button, so this sketch takes pains to turn that into an
 * edge detector.
 * 
 * Output:
 * -------
 * The sketch has one output: an RGB BlinkM LED connected to pins analog 2345.
 *
 * Command/Control:
 * ----------------
 * This sketch is commanded via serial, with a single command:
 * "s123" - where "123" is the number of minutes the button should 
 *          decay its light for.  If no 's' value is given, 60 mins is default
 * 
 * This sketch outputs three different lines:
 * "state: off"       -- the button has not been pressed
 * "state: decaying"  -- the button has been pressed recently 
 * "state: triggered! -- the button was *just* pressed (since last 's' call)
 *
 *
 * 2010, Tod E. Kurt, http://todbot.com/blog/
 *
 */

#include "Wire.h"
#include "BlinkM_funcs.h"

//unsigned long durationSecs = 10 * 60; // 10min * 60sec/min
unsigned long durationSecs = 2 * 60; 

const int debug = 0;

const int ledPin = 13;   // select the pin for the LED
const int swPin  = 8;

byte swState;
byte swStateLast;
byte swSave;

const byte c1r = 255;
const byte c1g = 255;
const byte c1b = 255;

const byte c2r = 255;
const byte c2g = 0;
const byte c2b = 0;

byte cr;
byte cg;
byte cb;

int baddr = 0;  // address all blinkm

unsigned long secs;
unsigned long lastMillis;


// arduino setup, called once at reset
void setup() {
  BlinkM_beginWithPower();
  delay(1000);
  
  pinMode(ledPin,OUTPUT);    // declare the LED's pin as output
  Serial.begin(19200);        // connect to the serial port
  Serial.print("BigButton: initializing...");
  Serial.println(durationSecs*1000 );

  
  pinMode(swPin, INPUT);           // set pin to input
  digitalWrite(swPin, HIGH);       // turn on pullup resistors

  swStateLast = digitalRead(swPin);
  
  BlinkM_stopScript(baddr);
  BlinkM_fadeToRGB(baddr, 0,0,0 );
  BlinkM_setFadeSpeed(baddr, 4 );

  Serial.println("BigButton: ready");
}

// arduino loop, called over and over again
void loop () {  
  int i;
  if( Serial.available() ) {    
    digitalWrite(ledPin, HIGH);
    int val = Serial.read();      // read the serial port  
    if( val == 's' ) {
      delay(10); // FIXME: small delay to let rest of serial string get buffered
      long st = millis();
      int i=0;
      char str[10];
      while( Serial.available() && i<10 && ((millis() - st) < 5000) ) {
        str[i++] = Serial.read();
      }
      str[i]=0; // null-terminate for atoi
      val = atoi(str);
      Serial.print("updateMins:");
      Serial.println( val) ;
      Serial.print("state: ");
      Serial.println((swSave)?"triggered!":((secs==0)?"off":"decaying"));
      swSave = 0;
      if( val != 0 ) { 
        durationSecs = val * 60; // 
      } else { 
          BlinkM_setRGB( baddr, 0,0,0 );
          secs = 0;  // reset
      }
    }
    digitalWrite(ledPin, LOW);
  }

  if( millis() % 100 == 0 ) { // read button every 100 msec
    int s = digitalRead(swPin);
    swState = ( s != swStateLast ) ? 1 : 0;
    swStateLast = s;
    if(debug>2) Serial.println( (swState)?"triggered!":"nope");
    if( swState ) {
      swSave = 1;

      secs = durationSecs; // reset our seconds counter on button pressx
      
      cr = c1r; cg = c1g; cb = c1b;
      BlinkM_setRGB( baddr, cr, cg, cb );
    }
  }

  // update every second
  if( millis() - lastMillis >= 1000 ) {
    lastMillis = millis();
    if( secs > 0 ) {
      secs--;
      cb = map( secs, 0,durationSecs, 0,255 );
      cg = cb;
    }
    else {
      cr = 0;
      cb = 0;
      cg = 0;
    }
    if(debug>1) { Serial.print("secstep:");Serial.println(cb,DEC); }
    if( secs % 2 == 0 ) { // breathe every 2 secs
      BlinkM_fadeToRGB( baddr, 2*cr/3,2*cg/2,2*cb/2 );
    }
    else { // normal
      BlinkM_fadeToRGB( baddr, cr,cg,cb );
    }
  }

}




  /*
  // fade out function
  if( millis() - millisLast > millisStep ) {
    if( cb > 0 ) { // use blue as our counter
      cg--; cb--;
    }
    else { // cb == 0
      cr = cg = cb = 0;
    }
    if(debug>1) { Serial.print("millistep:");Serial.println(cb,DEC); }

    BlinkM_fadeToRGB( baddr, cr,cg,cb );

    millisLast = millis();
  }
  */

/* this doesn't work in weird ways, need to poke at why
typedef struct _color {
  byte r; byte g; byte b;
} color;

const color c1 = {255,255,255};
const color c2 = {255,0,0};
color c;
*/
